package entity

import (
	. "data/datatype"
	"errors"
)

type BaseObj struct {
	ObjectType int

	mdirty  map[string]interface{}
	mmodify map[string]interface{}

	name string //名称

	//表格定义
	tool_r BaseObjTool //道具表
}

//获取类型
func (obj *BaseObj) Type(p string) (int, string, error) {
	switch p {

	case "Name":
		return DT_STRING, "string", nil

	default:
		return DT_NONE, "", errors.New("Type(" + p + ") property not found")
	}
}

//通过属性名设置值
func (obj *BaseObj) Set(p string, v interface{}) error {
	switch p {

	case "Name":
		val, ok := v.(string)
		if ok {
			obj.SetName(val)
		} else {
			return errors.New("Set(Name) value type mismatch")
		}

	default:
		return errors.New("Set(" + p + ") property not found")
	}

	return nil
}

//通过属性名获取值
func (obj *BaseObj) Get(p string) (val interface{}, err error) {
	switch p {

	case "Name":
		return obj.name, nil

	default:
		return nil, errors.New("Get(" + p + ") property not found")
	}
}

//是否需要同步到其它客户端
func (obj *BaseObj) IsPublic(p string) bool {
	switch p {

	default:
		return false
	}
}

//是否需要同步到自己的客户端
func (obj *BaseObj) IsPrivate(p string) bool {
	switch p {

	default:
		return false
	}
}

//是否需要存档
func (obj *BaseObj) IsSave(p string) bool {
	switch p {

	case "Name":
		return true

	default:
		return false
	}
}

//脏标志(数据保存用)
func (obj *BaseObj) setDirty(p string, v interface{}) {
	obj.mdirty[p] = v
}

func (obj *BaseObj) GetDirty() map[string]interface{} {

	return obj.mdirty
}

func (obj *BaseObj) ClearDirty() {
	for k := range obj.mdirty {
		delete(obj.mdirty, k)
	}
}

//修改标志(数据同步用)
func (obj *BaseObj) setModify(p string, v interface{}) {
	obj.mmodify[p] = v
}

func (obj *BaseObj) GetModify() map[string]interface{} {
	return obj.mmodify
}

func (obj *BaseObj) ClearModify() {
	for k := range obj.mmodify {
		delete(obj.mmodify, k)
	}
}

//名称
func (obj *BaseObj) SetName(v string) {
	obj.name = v
	obj.setDirty("Name", v)
}

func (obj *BaseObj) GetName() string {
	return obj.name
}

//BaseObjTool
type BaseObjTool struct {
	maxRows int
	cols    int
	rows    []BaseObjToolRow
	dirty   bool
}

//BaseObjTool行定义
type BaseObjToolRow struct {
	id   int32  //ID
	name string //名称
}

//表格的容量
func (rec *BaseObjTool) Cap() int {
	return rec.maxRows
}

//表格当前的行数
func (rec *BaseObjTool) Rows() int {
	return len(rec.rows)
}

//获取列定义
func (rec *BaseObjTool) ColTypes() ([]int, []string) {
	col := []int{DT_INT32, DT_STRING}
	cols := []string{"int32", "string"}
	return col, cols
}

//获取列数
func (rec *BaseObjTool) Cols() int {
	return rec.cols
}

//脏标志
func (rec *BaseObjTool) Dirty() bool {
	return rec.dirty
}

func (rec *BaseObjTool) ClearDirty() {
	rec.dirty = false
}

//通过行列设置值
func (rec *BaseObjTool) Set(row, col int, val interface{}) error {
	if row < 0 || row >= len(rec.rows) {
		return errors.New("row error")
	}

	if col < 0 || col >= 2 {
		return errors.New("col error")
	}

	r := rec.rows[row]

	switch col {

	case 0:
		val, ok := val.(int32)
		if ok {
			r.id = val
		} else {
			return errors.New("val type mismatch")
		}

	case 1:
		val, ok := val.(string)
		if ok {
			r.name = val
		} else {
			return errors.New("val type mismatch")
		}

	}

	rec.dirty = true
	return nil
}

//通过行列获取值
func (rec *BaseObjTool) Get(row, col int) (val interface{}, err error) {
	if row < 0 || row >= len(rec.rows) {
		err = errors.New("row error")
		return
	}

	if col < 0 || col >= 2 {
		err = errors.New("col error")
		return
	}

	r := rec.rows[row]

	switch col {

	case 0:
		val = r.id

	case 1:
		val = r.name

	}

	return
}

//设置ID
func (rec *BaseObjTool) SetId(row int, v int32) error {
	if row < 0 || row >= len(rec.rows) {
		return errors.New("row error")
	}

	rec.rows[row].id = v
	rec.dirty = true
	return nil
}

//获取ID
func (rec *BaseObjTool) GetId(row int) (val int32, err error) {
	if row < 0 || row >= len(rec.rows) {
		err = errors.New("row error")
		return
	}

	val = rec.rows[row].id
	return
}

//设置名称
func (rec *BaseObjTool) SetName(row int, v string) error {
	if row < 0 || row >= len(rec.rows) {
		return errors.New("row error")
	}

	rec.rows[row].name = v
	rec.dirty = true
	return nil
}

//获取名称
func (rec *BaseObjTool) GetName(row int) (val string, err error) {
	if row < 0 || row >= len(rec.rows) {
		err = errors.New("row error")
		return
	}

	val = rec.rows[row].name
	return
}

//增加一行,row=-1时,在表格最后面插入一行,否则在row处插入,返回-1插入失败,否则返回插入的行号
func (rec *BaseObjTool) Add(row int, id int32, name string) int {
	add := -1

	if len(rec.rows) >= rec.maxRows {
		return add
	}

	r := BaseObjToolRow{id, name}

	if row == -1 {
		rec.rows = append(rec.rows, r)
		add = len(rec.rows) - 1
	} else {
		if row >= 0 && row < len(rec.rows) {
			rec.rows = append(rec.rows, BaseObjToolRow{})
			copy(rec.rows[row+1:], rec.rows[row:])
			rec.rows[row] = r
			add = row
		} else {
			rec.rows = append(rec.rows, r)
			add = len(rec.rows) - 1
		}

	}
	if add != -1 {
		rec.dirty = true
	}
	return add
}

//获取数据
func (rec *BaseObjTool) Scan(row int, id *int32, name *string) bool {

	if row < 0 || row >= len(rec.rows) {
		return false
	}

	r := rec.rows[row]
	*id = r.id
	*name = r.name

	return true
}

//删除一行
func (rec *BaseObjTool) Del(row int) {
	if row >= 0 {
		if len(rec.rows) > 1 {
			if row == 0 {
				copy(rec.rows[:], rec.rows[1:])
			} else {
				copy(rec.rows[row:], rec.rows[row+1:])
			}
			rec.rows = rec.rows[:len(rec.rows)-1]
			rec.dirty = true
		} else {
			rec.Clear()
		}
	}
}

//清空表格
func (rec *BaseObjTool) Clear() {
	rec.rows = rec.rows[:0]
	rec.dirty = true
}

//初始化tool表
func (obj *BaseObj) initBaseObjTool() {
	obj.tool_r.maxRows = 256
	obj.tool_r.cols = 2
	obj.tool_r.rows = make([]BaseObjToolRow, 0, 256)
}

//获取BaseObjTool表
func (obj *BaseObj) GetBaseObjTool() *BaseObjTool {
	return &obj.tool_r
}

//初始化所有的表格
func (obj *BaseObj) initRec() {
	obj.initBaseObjTool()

}

//获取某个表格
func (obj *BaseObj) GetRec(rec string) interface{} {
	switch rec {

	case "Tool":
		return &obj.tool_r

	default:
		return nil
	}
}

//由子类调用的初始化函数
func (obj *BaseObj) baseInit(dirty, modify map[string]interface{}) {
	//初始化表格
	obj.initRec()

	obj.mdirty = dirty
	obj.mmodify = modify

}

//创建函数
func CreateBaseObj() *BaseObj {
	obj := &BaseObj{}
	obj.ObjectType = NONE
	obj.initRec()

	obj.mdirty = make(map[string]interface{})
	obj.mmodify = make(map[string]interface{})
	return obj
}
